package com.zzzs.synchronizeddemo;

/**
 * notify
 * 从等待线程中随机唤醒一个
 * @author zhu_shuai
 * @since 8/11
 */
public class NotifyDemo {
    public static void main(String[] args) throws InterruptedException {
        Object obj = new Object();

        Thread thread1 = new Thread(new RunnableWait(obj));
        Thread thread2 = new Thread(new RunnableWait(obj));
        Thread thread3 = new Thread(new RunnableWait(obj));
        /*
         * 三个线程进入阻塞状态
         */
        thread1.start();
        thread2.start();
        thread3.start();


        /*
         * 三秒后随机唤醒一个等待线程
         */
        // Thread.sleep(3000);
        // Thread thread4 = new Thread(new RunnableNotify(obj));
        // thread4.start();

        Thread.sleep(3000);
        Thread thread5 = new Thread(new RunnableNotifyAll(obj));
        /*
         * 唤醒所有等待线程
         */
        thread5.start();
    }
}

class RunnableWait implements Runnable{
    private final Object obj;

    public RunnableWait(Object obj) {
        this.obj = obj;
    }

    @Override
    public void run() {
        System.out.printf("waitName: %s %n", Thread.currentThread().getName());
        synchronized (obj) {
            System.out.printf("waitName: %s 进入锁%n", Thread.currentThread().getName());
            try {
                obj.wait(); // 进入等待，释放锁资源
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.printf("waitName: %s 退出锁%n", Thread.currentThread().getName());
        }
    }
}

class RunnableNotify implements Runnable{
    private final Object obj;

    public RunnableNotify(Object obj) {
        this.obj = obj;
    }

    @lombok.SneakyThrows
    @Override
    public void run() {
        System.out.printf("notifyName: %s %n", Thread.currentThread().getName());
        synchronized (obj) {
            System.out.printf("notifyName: %s 进入锁%n", Thread.currentThread().getName());
            // 随机唤醒一个等待线程
            obj.notify();
            System.out.printf("notifyName: %s 退出锁%n", Thread.currentThread().getName());
        }
    }
}

class RunnableNotifyAll implements Runnable{
    private final Object obj;

    public RunnableNotifyAll(Object obj) {
        this.obj = obj;
    }

    @lombok.SneakyThrows
    @Override
    public void run() {
        System.out.printf("notifyAllName: %s %n", Thread.currentThread().getName());

        synchronized (obj) {
            System.out.printf("notifyAllName: %s 进入锁%n", Thread.currentThread().getName());
            // 唤醒所有等待线程
            obj.notifyAll();
            System.out.printf("notifyAllName: %s 退出锁%n", Thread.currentThread().getName());
        }
    }
}

